<?php
/**
*首信易支付接口控制器
*/
namespace Home\Controller;
use Think\Controller;
class PayeaseController extends CommonController{

//支付网关
private  $gateway_url="https://pay.beijing.com.cn/customer/i18n/i18n_pay_direct.jsp";
private  $refund_gateway="https://api.yizhifubj.com/merchant/refund/ref_ack_submit.jsp";
	/**
	*接口订单处理函数
	*@param array $channel_info 通道信息
	*@param array $site_info 交易网站信息
	*@param array $order_info 订单信息
	*/
public function process($channel_info,$site_info,$order_info){


//0为人民币，1为美元，2为欧元，3为英镑，4为日元，5为韩元，6为澳大利亚元
$v_moneytype=0;//统一首信易的货币类型为人民币
//商户配货状态，0为未配齐，1为已配齐
$v_orderstatus=1;
//提交的IP地址
$v_ordip= $order_info['order_source_ip'];
//订单生成日期(yyyymmdd)-商户编号-商户流水号
$v_oid=date("Ymd")."-".$channel_info["cn_key1"]."-".$order_info['order_id'];

//17-VISA, 18-MASTER, 19-AE, 20-JCB
switch($order_info["card_type"]){
	case "visa":
	$v_pmode=17;
	break;
	case "mastercard":
	$v_pmode=18;
	break;
	case "amex":
	$v_pmode=19;
	break;
	case "jcb":
	$v_pmode=20;
	break;
}


$v_ymd=date("Ymd");
$v_rcvname=$channel_info["cn_key1"];
$v_url=$this->web_config["web_domain"];

//v_moneytype v_ymd v_amount v_rcvname v_oid v_mid v_url
//首信易需要加密的字符串
$md5_data=$v_moneytype.$v_ymd.$order_info["gateway_amount"].$v_rcvname.$v_oid.$channel_info["cn_key1"].$v_url;
//提交给首信易的加密
$v_md5_info=$this->hmac($channel_info["cn_key2"],$md5_data);

//street不能超过50个字符
$cur_street=substr($order_info['bill_street'],0,50);

//以下代码修改IPS订单号
//第一步，先写入数据IPS订单号
$order=new \Common\Common\OrderProcess($order_info['order_id']);
$order_data['ips_id']=$v_oid;
$order->magicProcess($order_data);


/////////////////////////////
$curlPost.="v_oid=".$v_oid;//订单号
$curlPost.="&v_mid=".$channel_info["cn_key1"];//商户号

$curlPost.="&v_rcvname=".$v_rcvname;
$curlPost.="&v_rcvaddr=".$cur_street;
$curlPost.="&v_rcvtel=".$order_info['bill_phone'];
$curlPost.="&v_rcvpost=".$order_info['bill_zip'];

//订单信息
$curlPost.="&v_amount=".$order_info["gateway_amount"];
$curlPost.="&v_ymd=".$v_ymd;
$curlPost.="&v_orderstatus=".$v_orderstatus;
$curlPost.="&v_ordername=".$v_rcvname;
$curlPost.="&v_moneytype=".$v_moneytype;
$curlPost.="&v_url=".$v_url;//固定值，实际不会使用
$curlPost.="&v_md5info=".$v_md5_info;

//信用卡信息
$curlPost.="&v_pmode=".$v_pmode;
$curlPost.="&v_card_holder=".$order_info['bill_firstname'].$order_info["bill_lastname"];
$curlPost.="&v_card_no=".$order_info['cc_cardid'];
$curlPost.="&v_expire_m=".$order_info['cc_expiry_month'];
$curlPost.="&v_expire_y=".$order_info['cc_expiry_year'];
$curlPost.="&v_card_cvv2=".$order_info['cc_cvv'];
$curlPost.="&v_ordip=".$v_ordip;

/*
首信易国家需要使用国际代码数字，需要转化
*/
$loader = new \Phine\Country\Loader\Loader();
$country = $loader->loadCountry($order_info["bill_country"]);
$country_code=$country->getNumericCode();

$curlPost.="&v_shipstreet=".$cur_street;
$curlPost.="&v_shipcity=".$order_info['bill_city'];
$curlPost.="&v_shipstate=".$order_info['bill_state'];
$curlPost.="&v_shippost=".$order_info['bill_zip'];
$curlPost.="&v_shipcountry=".$country_code;
$curlPost.="&v_shipphone=".$order_info['bill_phone'];
$curlPost.="&v_shipemail=".$order_info['bill_email'];
$curlPost.="&v_billstreet=".$cur_street;
$curlPost.="&v_billcity=".$order_info['bill_city'];
$curlPost.="&v_billstate=".$order_info['bill_state'];
$curlPost.="&v_billpost=".$order_info['bill_zip'];
$curlPost.="&v_billcountry=".$country_code;
$curlPost.="&v_billphone=".$order_info['bill_phone'];
$curlPost.="&v_billemail=".$order_info['bill_email'];

//dump($curlPost);
//exit;

$ch=curl_init();
curl_setopt($ch,CURLOPT_URL,$this->gateway_url);
curl_setopt($ch,CURLOPT_POST,1);
curl_setopt($ch,CURLOPT_POSTFIELDS,$curlPost);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_TIMEOUT,20);   //20秒超时时间
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,  2);

//以下代码效果，当判断返回代码为空时，则提交三次
for($index_key=1;$index_key<=3;$index_key++){
	$back_data=trim(curl_exec($ch));
	if($back_data && 
	!strstr($back_data,"503 Service Temporarily Unavailable") && 
	!strstr($back_data,"[92]The issuing bank or the switching center is unavailable"))
		break;
}
curl_close($ch);


$payment_result=explode("\r\n",$back_data);
$arr;
foreach ($payment_result as $key => $val) {
$i=explode("=",$val);
$arr[$i[0]]=$i[1];
}

//dump($arr);
//exit;

//计入系统通知，可以查看通知情况
$in_title="【".$index_key."】首信易接口(credit card)-Payease/index-直连即时通知-".$v_oid."-".$arr["v_pstatus"];
$in_content=dump($arr,false)."<hr>".$back_data.'<hr>'.$curlPost;
$in_oid=$order_info['order_id'];
$this->inputIPS($in_title,$in_content,$in_oid);
/////////////////////////////////////

//返回异常，订单是待处理状态
if($arr['v_status']!=0 && $arr['v_status']!=1){
$bk_data['order_status']=1;	
return $bk_data;
}


if($arr['v_status']==1){//交易异常
if(strstr($arr['v_statusdesc'],"(400008)") 
	|| strstr($arr['v_statusdesc'],"(400103)") 
	|| strstr($arr['v_statusdesc'],"(400019)")){
	$bk_data['order_status']=1;
}else{
//交易失败
$order->toDecline($arr['v_statusdesc']);	
$bk_data['order_status']=6;//declined
$bk_data['order_failed_reason']=$arr['v_statusdesc'];
}
return $bk_data;
}


switch($arr['v_pstatus']){
case "1"://提交
case "10":
$bk_data['order_status']=1;	
break;
case "20"://成功
case "11":
$order->toApprove();
$order_info['process_mode']==0?$bk_data['order_status']=3:$bk_data['order_status']=2;
break;
case "30"://失败
case "12":
$order->toDecline($arr['v_pstring']);
$bk_data['order_status']=6;
$bk_data['order_failed_reason']=$arr['v_pstring'];

//添加黑卡
//判断返回错误代码，添加黑卡库	
if((strstr($arr['v_pstring'],'[14]')
||	strstr($arr['v_pstring'],'[41]')
||  strstr($arr['v_pstring'],'[43]'))
&& $order_info['cc_cardid']!="4391880502212396"
){
	$bc['bl_value']=$order_info['cc_cardid'];
	$bc["bl_remark"]=$arr['v_pstring']."|订单号：".$order_info["order_id"];
	$bc['bl_value1']=$order_info["cc_cvv"];
	$bc["bl_value2"]=$order_info["cc_expiry_year"];
	$bc["bl_value3"]=$order_info["cc_expiry_month"];
	$this->inputBlacklist($bc,"CreditCard");
}
break;
}
return $bk_data;

/*
10 （预授权未处理，预授权交易没有银行结果）
11 （预授权成功，预授权交易成功）
12 （预授权失败，预授权交易失败）

参考请求响应输出内容如下：
v_status=0
v_statusdesc=Success
v_oid=20100713-888-142439 
v_pmode=实时外卡
v_pstatus=20
v_pstring=支付成功
v_md5info=a595bdd3ee36558779e65854cca02ca3 
v_amount=1
v_moneytype=1
v_md5money=35bbc3aead9b69ce474854e7a02240ab 
v_sign=b356aca7e356634a1b79e14fdba53838ac87c8f8806e876b6696d62ece6942c3742deae49a921110bca3ef809b531e336e89d1aa06acf5f92531161fd823efcaae781d90b2a55635d79b162b53dc3460653163bd37bd92c5f62d23abee87e38da58eb2a3d950b429c0b6dda7414ef9ac644766494ab71aed6f33a5faa20c1ed9 
v_authcode=11111
*/
}


	/**
	*接口订单退款处理函数
	*@param array $order_info 退款订单信息
	*@param decimal(12,2) refund_amount 退款金额
	*@return bool  返回是否成功退款的通知
	*/
public function refund($order_info,$refund_amount){
	
$curlPost.="v_mid=".$order_info['cn_key1'];//商户号
$curlPost.="&v_oid=".$order_info['ips_id'];//通道流水号
$curlPost.="&v_refamount=".$refund_amount;
$curlPost.="&v_refreason=Customer requests money back.[".date("Y-m-d H:i:s")."]";
$curlPost.="&v_refoprt=".$order_info['cn_key3'];

$md5_data=$order_info['cn_key1'].$order_info['ips_id'].$refund_amount.$order_info['cn_key3'];
$v_mac=$this->hmac($order_info['cn_key2'],$md5_data);

$curlPost.="&v_mac=".$v_mac;

$ch=curl_init();
//curl_setopt($ch,CURLOPT_URL,"http://210.73.90.18/merchant/refund/ref_ack_submit.jsp");
curl_setopt($ch,CURLOPT_URL,$this->refund_gateway);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('X-FORWARDED-FOR:64.64.8.192', 'CLIENT-IP:64.64.8.192'));
curl_setopt($ch,CURLOPT_POST,1);
curl_setopt($ch,CURLOPT_POSTFIELDS,$curlPost);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,  2);
$back_data=trim(curl_exec($ch));
curl_close($ch);

$xml = simplexml_load_string($back_data);

//ips通知
$in_title="首信易(credit card)-自动退款-".$order_info["order_id"]."-".$xml->status;
$in_content=dump($curlPost,false)."<hr>".dump($back_data,false)."<hr>".dump($xml,false);
$this->inputIPS($in_title,$in_content,$order_info["order_id"]);

$order=new \Common\Common\OrderProcess($order_info["order_id"]);
if($xml && $xml->status==0){
//退款成功
$order->toRefund();
return true;	
}else{
return false;	
}
}


//首信易延迟通知地址
public function asyNotify(){

foreach(I() as $key=>$value){
$arr[$key]=iconv('GB2312', 'UTF-8',$value);
}
//dump($arr);
//exit;

//IPS通知
$in_title="Payease/asyNotify-首信易异步通知-".I("v_oid")."-".$arr["v_pmode"]."-".$arr["v_pstring"];
$in_content=dump($arr,false);
$in_oid=I("v_oid");
$this->inputIPS($in_title,$in_content,$in_oid);
//--------------------------------------------------
//echo("sent");


//接收返回的参数
$v_oid=$_REQUEST['v_oid'];//订单编号组
$v_pmode= $_REQUEST['v_pmode'];//支付方式组
$v_pstatus=$_REQUEST['v_pstatus'];//支付状态组
$v_pstring= $_REQUEST['v_pstring'];//支付结果说明
$v_amount=$_REQUEST['v_amount'];//订单支付金额
$v_count=$_REQUEST['v_count'];//订单个数
$v_moneytype=$_REQUEST['v_moneytype'];//订单支付币种
$v_mac=$_REQUEST['v_mac'];//数字指纹（v_mac）
$v_md5money=$_REQUEST['v_md5money'];//数字指纹（v_md5money）
$v_sign=$_REQUEST['v_sign'];//验证商城数据签名（v_sign）
//拆分参数
$sp = '|_|';
$a_oid = explode($sp, $v_oid);
$a_pmode = explode($sp, $v_pmode);
$a_pstatus = explode($sp, $v_pstatus);
$a_pstring = explode($sp, $v_pstring);
$a_amount = explode($sp, $v_amount);
$a_moneytype = explode($sp, $v_moneytype);

//------------------------------------------------------
/*
dump($arr);
foreach($a_oid as $key=>$value){
$value_oid=explode('-',$value);
echo $value_oid[2];
dump($a_pstatus[$key]);
exit;
}
exit;
*/




//查看第一笔交易的通道
$order_oop=M("orders");
$arr_oid1=explode('-',$a_oid[0]);
$order_con['order_id']=$arr_oid1[2];
$order_list=$order_oop->where($order_con)->find();
//dump($order_list);
if(!$order_list){
exit("error1");
}
//查看通道
$ch_con['cn_id']=$order_list['order_channel'];
$ch_list=M("channels")->where($ch_con)->find();
if(!$ch_list){
exit("error2");
}


//$v_md5_info=hmac($channel_list["cn_key2"],$md5_data);
//v_oid+v_pmode+v_pstatus+v_pstring+v_count
$md5_data=$v_amount.$v_moneytype;
$md5_info=hmac($ch_list['cn_key2'],$md5_data);
//dump($v_md5money);
if($md5_info!=$v_md5money){
exit("error");
}


/*
0→待处理（支付结果未确定）；
1支付完成；
3支付被拒绝； 
*/

foreach($a_oid as $key=>$value){
$value_oid=explode('-',$value);
$order_list=$order_oop->find($value_oid[2]);
$order_list['ips_id']=$value;

switch($order_list['order_status']){
case 1://pending
//exit($a_pstatus[$key]);
switch($a_pstatus[$key]){
case 1:
//判断是预授权还是消费
if($order_list['order_type']==1){
$order_list['order_status']=2;
}else{
$order_list['order_status']=6;
}
orderProcess($order_list);
break;
case 3:
$order_list['order_status']=7;
//dump($order_list);
//exit;
orderProcess($order_list);
break;


default:
$str.="订单号：".$value."-|-平台状态:".$order_list['order_status']."-|-首信易状态:".$a_pstatus[$key]."<hr>";
}


break;
case 2://authorized
case 4://captured
case 6://approved
if($a_pstatus[$key]!=1){
$str.="订单号：".$value."-|-平台状态:".$order_list['order_status']."-|-首信易状态:".$a_pstatus[$key]."<hr>";
}

break;
case 3://declined
case 7://failed
if($a_pstatus[$key]!=3){
$str.="订单号：".$value."-|-平台状态:".$order_list['order_status']."-|-首信易状态:".$a_pstatus[$key]."<hr>";
}
break;
case 5://voided
case 8://refunded
case 9://chargeback
case 10://entered
case 11://pending refund
case 12://returned
case 13://pending return
$str.="订单号：".$value."-|-平台状态:".$order_list['order_status']."-|-首信易状态:".$a_pstatus[$key]."<hr>";
break;
}
}
//发送邮件
if($str!=""){
$header="<h1>首信易异步对账</h1>";
$body=$header.$str;
$to="vivians@austpay.com";
$subject="首信易订单状态异步通知";
email_to($to,$subject,$body);
}

echo("sent");

}

//首信易计算MD5方法
private function hmac ($key, $data){
// 创建 md5的HMAC
$b = 64; // md5加密字节长度
if (strlen($key) > $b) {
$key = pack("H*",md5($key));
}
$key  = str_pad($key, $b, chr(0x00));
$ipad = str_pad('', $b, chr(0x36));
$opad = str_pad('', $b, chr(0x5c));
$k_ipad = $key ^ $ipad;
$k_opad = $key ^ $opad;

return md5($k_opad  . pack("H*",md5($k_ipad . $data)));
}


}
?>